local skynet = require "skynet"
local PlayerService = require "modules.player.PlayerService"
local RoomConst = require "modules.room.RoomConst"
local Room = require "modules.room.Room"
local RoomEvent = require "modules.room.RoomEvent"
local PlayerEvent = require "modules.player.PlayerEvent"
local GamesConfig = require "modules.games.GamesConfig"
local games = GamesConfig.games

local M = {}

local curRoomId = 99999
-- roomId -> room
local rooms = {}
-- playerId -> room
local player2room = {}
--- gameName -> room
local gameRooms = {}

local function getRoomId()
    if curRoomId > 999999 then
        curRoomId = 99999
    end

    curRoomId = curRoomId + 1
    return curRoomId
end

function M.createRoom(playerId, data)
    if player2room[playerId] then
        return RoomConst.CREATE_RESULT_CODE.ALREADY_IN_ROOM
    end

    local rule = data.rule
    local coinNeed = M.coinNeed(data.gameName, rule)
    if not PlayerService:decrementCoin(playerId, coinNeed) then
        return RoomConst.CREATE_RESULT_CODE.COIN_NOT_ENOUGH
    end

    -- 创建房间
    local roomId = getRoomId()
    local service = skynet.new_hotservice("modules/room/Room")
    if not skynet.call(service, "lua", "start", roomId, data, playerId) then
        return RoomConst.CREATE_RESULT_CODE.FAIL
    end

    local room = {
        service = service,
        id = roomId,
        gameName = data.gameName,
        players = {playerId}
    }

    player2room[playerId] = room
    rooms[roomId] = room
    gameRooms[data.gameName] = gameRooms[data.gameName] or {}
    gameRooms[data.gameName][roomId] = room
    return RoomConst.CREATE_RESULT_CODE.SUCCESS, service
end

function M.coinNeed(gameName, rule)
    return 0
end

function M.enterRoom(playerId, roomId)
    if not rooms[roomId] then
        return RoomConst.ENTER_RESULT_CODE.ROOM_NOT_EXIST
    end

    if player2room[playerId] then
        return RoomConst.ENTER_RESULT_CODE.ALREADY_IN_ROOM
    end

    return RoomConst.ENTER_RESULT_CODE.SUCCESS, rooms[roomId].service
end

function M.onPlayerEnter(playerId, roomId)
    local room = rooms[roomId]
    assert(rooms[roomId], "enter room not exist, roomId: " .. tostring(roomId))
    table.insert(room.players, playerId)
    player2room[playerId] = roomId
end

function M.onPlayerExit(playerId)
    local room = player2room[playerId]
    assert(room, "exit room not exist, player: " .. tostring(playerId))
    player2room[playerId] = nil
    table.remove(room.players, table.index(room.players, playerId))
end

function M.onDismiss(roomId)
    local room = rooms[roomId]
    assert(rooms[roomId], "dismiss room not exist, roomId: " .. tostring(roomId))
    rooms[roomId] = nil
    gameRooms[room.gameName][roomId] = nil
    for _, playerId in pairs(room.players) do
        player2room[playerId] = nil
    end
end

function M.getPlayerRoom(playerId)
    if not player2room[playerId] then
        return
    end

    return player2room[playerId].id
end

function M.playerData(playerId)
end

function M.start()
end

function M.listeners()
    return {
        [RoomEvent.ROOM_PLAYER_ENTER] = M.onPlayerEnter,
        [RoomEvent.ROOM_PLAYER_EXIT] = M.onPlayerExit,
        [RoomEvent.ROOM_DISMISS] = M.onDismiss
    }
end

function M.init()
    skynet.dispatch_lua_queue(M)
end

return M
